Integration Credentials Guide
This guide explains how to configure credentials for 600+ integrations in ATOM SaaS.
š Credential Architecture
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ATOM SaaS Platform ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā .env (Platform-Level) ā Database (Tenant-Level) ā
ā āāāāāāāāāāāāāāāāāāāāā ā āāāāāāāāāāāāāāāāāāāāāāāā ā
ā OAuth App IDs/Secrets ā User OAuth Tokens ā
ā Platform API Keys ā BYOK API Keys (OpenAI) ā
ā Stripe/SendGrid Keys ā Integration Connections ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāš„ Push vs Pull Data Sync
Which Apps Require Scheduled Pulling?
**~40% of integrations require scheduled polling** because they don't offer webhooks or have limited real-time capabilities.
| Integration | Sync Type | Details |
|---|---|---|
| **Slack** | ā PUSH | Real-time Events API - instant |
| **Shopify** | ā PUSH | Webhooks for orders, products, customers |
| **HubSpot** | ā PUSH | Webhook subscriptions for all CRM events |
| **Salesforce** | ā PUSH | Streaming API + Outbound Messages |
| **Stripe** | ā PUSH | Webhooks for payments, subscriptions |
| **GitHub** | ā PUSH | Webhooks for commits, PRs, issues |
| **Jira** | ā PUSH | Webhooks for issue changes |
| **Linear** | ā PUSH | Webhooks available |
| **Gmail** | ā ļø HYBRID | Push notifications for new mail + pull for history |
| **Outlook** | ā ļø HYBRID | Change notifications expire, need re-subscribe |
| **Google Calendar** | ā ļø HYBRID | Push notifications + pull for full sync |
| **Airtable** | ā ļø HYBRID | Webhooks only on paid plans; free = poll |
| **MS Teams** | ā ļø HYBRID | Subscriptions expire after 60 min |
| **QuickBooks** | ā PULL | No webhooks - must poll Change Data Capture API |
| **Xero** | ā PULL | Very limited webhooks - mostly polling |
| **Notion** | ā PULL | **No webhooks at all** - polling only |
| **Zoho CRM** | ā PULL | Webhooks unreliable - recommend polling |
| **Monday.com** | ā PULL | Webhooks are premium feature |
| **Dropbox** | ā ļø HYBRID | Webhooks for file changes, polling for details |
| **Box** | ā PUSH | Webhooks for all events |
Real-Time vs Scheduled Sync (Tier-Based)
Your SyncOrchestrator handles polling automatically based on subscription tier:
// From src/lib/sync/orchestrator.ts
SYNC_INTERVALS = {
FREE: 'WEEKLY', // Every 7 days (poll-only apps)
SOLO: 'DAILY', // Every 24 hours
TEAM: 'HOURLY', // Every hour
ENTERPRISE: 'REAL_TIME' // Webhook-first, poll as backup
}---
š ļø Platform Credentials (.env)
These are YOUR OAuth app credentials (not customer's).
Required for Core Features
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# CORE PLATFORM
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
DATABASE_URL="postgresql://user:pass@host:5432/atom_saas?sslmode=require"
REDIS_URL="redis://user:pass@host:6379"
JWT_SECRET="generate-with-openssl-rand-base64-32"
NEXTAUTH_URL="https://app.atom-saas.com"
NEXTAUTH_SECRET="generate-with-openssl-rand-base64-32"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# BILLING & EMAIL
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
STRIPE_SECRET_KEY="sk_live_..."
STRIPE_PUBLISHABLE_KEY="pk_live_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID_SOLO="price_..."
STRIPE_PRICE_ID_TEAM="price_..."
STRIPE_PRICE_ID_ENTERPRISE="price_..."
SMTP_HOST="smtp.sendgrid.net"
SMTP_USER="apikey"
SMTP_PASS="SG...."
FROM_EMAIL="noreply@atom-saas.com"CRM Integrations
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# SALESFORCE
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: Setup ā Apps ā App Manager ā New Connected App
SALESFORCE_CLIENT_ID="3MVG9..."
SALESFORCE_CLIENT_SECRET="..."
SALESFORCE_CALLBACK_URL="https://app.atom-saas.com/api/integrations/salesforce/callback"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# HUBSPOT
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://developers.hubspot.com/
HUBSPOT_CLIENT_ID="..."
HUBSPOT_CLIENT_SECRET="..."
HUBSPOT_CALLBACK_URL="https://app.atom-saas.com/api/integrations/hubspot/callback"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# ZOHO
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://api-console.zoho.com/
ZOHO_CLIENT_ID="..."
ZOHO_CLIENT_SECRET="..."
ZOHO_CALLBACK_URL="https://app.atom-saas.com/api/integrations/zoho/callback"Communication Integrations
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# SLACK
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://api.slack.com/apps
SLACK_CLIENT_ID="..."
SLACK_CLIENT_SECRET="..."
SLACK_SIGNING_SECRET="..."
SLACK_CALLBACK_URL="https://app.atom-saas.com/api/integrations/slack/callback"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# GOOGLE (Gmail, Calendar, Drive)
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://console.cloud.google.com/
GOOGLE_CLIENT_ID="...apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="..."
GOOGLE_CALLBACK_URL="https://app.atom-saas.com/api/integrations/callback"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# MICROSOFT (Outlook, Teams, OneDrive)
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://portal.azure.com/ ā App registrations
MICROSOFT_CLIENT_ID="..."
MICROSOFT_CLIENT_SECRET="..."
MICROSOFT_TENANT_ID="common"
MICROSOFT_CALLBACK_URL="https://app.atom-saas.com/api/integrations/callback"E-commerce & Finance
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# SHOPIFY
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://partners.shopify.com/
SHOPIFY_API_KEY="..."
SHOPIFY_API_SECRET="..."
SHOPIFY_SCOPES="read_products,write_orders,read_customers"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# QUICKBOOKS
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://developer.intuit.com/
QUICKBOOKS_CLIENT_ID="..."
QUICKBOOKS_CLIENT_SECRET="..."
QUICKBOOKS_CALLBACK_URL="https://app.atom-saas.com/api/integrations/callback"
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# XERO
# āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
# Create app: https://developer.xero.com/
XERO_CLIENT_ID="..."
XERO_CLIENT_SECRET="..."
XERO_CALLBACK_URL="https://app.atom-saas.com/api/integrations/callback"---
šļø Tenant Credentials (Database)
When a user connects an integration, tokens are stored in tenant_settings:
-- Example: User connects their Salesforce account
INSERT INTO tenant_settings (tenant_id, setting_key, setting_value, encrypted)
VALUES (
'tenant-uuid',
'salesforce_tokens',
'{"access_token": "...", "refresh_token": "...", "instance_url": "..."}',
true
);
-- BYOK: User provides their own OpenAI key
INSERT INTO tenant_settings (tenant_id, setting_key, setting_value, encrypted)
VALUES (
'tenant-uuid',
'OPENAI_API_KEY',
'sk-proj-...',
true
);Token Refresh Flow
// Automatic token refresh (simplified)
async function refreshTokenIfNeeded(tenantId: string, integration: string) {
const settings = await getTenantSettings(tenantId);
const tokens = JSON.parse(settings[`${integration}_tokens`]);
if (isExpired(tokens.expires_at)) {
const newTokens = await oauthClient.refreshToken(tokens.refresh_token);
await saveTenantSetting(tenantId, `${integration}_tokens`, newTokens);
return newTokens;
}
return tokens;
}---
š Quick Setup Checklist
Minimum Viable Production
- [ ]
DATABASE_URL- PostgreSQL with SSL - [ ]
REDIS_URL- For rate limiting & caching - [ ]
JWT_SECRET/NEXTAUTH_SECRET- Generate secure secrets - [ ]
STRIPE_*- For billing - [ ]
SMTP_*- For transactional emails
Top 5 Integrations to Enable First
- [ ] **Slack** - Team communication (PUSH)
- [ ] **Google** - Gmail, Calendar, Drive (PULL + webhooks)
- [ ] **Salesforce** - CRM (PUSH + PULL)
- [ ] **Shopify** - E-commerce (PUSH via webhooks)
- [ ] **QuickBooks** - Finance (PULL)
---
š Security Best Practices
- **Never commit real credentials** - Use
.envfiles (gitignored) - **Encrypt tokens in database** - Use
encrypted: truecolumn - **Rotate secrets regularly** - Especially after team changes
- **Use least-privilege scopes** - Only request what you need
- **Monitor OAuth activity** - Log all token refreshes